<style type="text/css">
  table.event-state-transitions {
    width: 100%;
    border-spacing: 0px;
    border-collapse: collapse;
  }
  table.event-state-transitions th:first-child {
    width: 30%;
  }
  table.event-state-transitions th {
    text-align: center;
  }
  table.event-state-transitions td {
    padding: 0.2em 1em;
    border: 1px solid black;
  }
</style>

<pre class='metadata'>
Title: CSS Animations Module Level 2
Status: ED
Work Status: Exploring
Shortname: css-animations
Level: 2
Group: csswg
ED: https://drafts.csswg.org/css-animations-2/
TR: https://www.w3.org/TR/css-animations-2/
Editor: L. David Baron, Google https://www.google.com/, https://dbaron.org/, w3cid 15393
Editor: Brian Birtles, Invited Expert, brian@birchill.co.jp, w3cid 43194
!Issues List: https://github.com/w3c/csswg-drafts/labels/css-animations-2
Abstract: This CSS module describes a way for authors to animate the values of CSS properties over time, using keyframes. The behavior of these keyframe animations can be controlled by specifying their duration, number of repeats, and repeating behavior.
Ignored Vars: auto-rewind
</pre>
<!-- !Issues List: <a href="https://www.w3.org/Bugs/Public/buglist.cgi?component=Animations&list_id=36653&product=CSS&query_format=advanced&resolution=---">In Bugzilla</a> -->
<pre class=anchors>
urlPrefix: https://dom.spec.whatwg.org/; type: dfn; spec: dom
    text: event target
</pre>
<pre class=link-defaults>
spec:cssom-1; type:dfn;
    text:property name; for:CSS declaration
spec:web-animations-1; type:dfn;
    text:active duration
    text:active phase; for:animation effect
    text:active time
    text:after phase; for:animation effect
    text:animation class
    text:animation effect
    text:animation playback events
    text:associated effect
    text:associated effect end
    text:before phase; for:animation effect
    text:current iteration
    text:current time; for:animation
    text:composite operation
    text:fill mode
    text:idle play state
    text:idle phase; for:animation effect
    text:iteration duration
    text:iteration count
    text:iteration start
    text:keyframe
    text:pause an animation
    text:paused play state
    text:pending pause task
    text:pending play task
    text:play an animation
    text:play state
    text:playback direction
    text:start delay
    text:target element
    text:unresolved
spec:web-animations-2; type:dfn;
    text:active interval; for:animation trigger
    text:default range
    text:exit range
spec:scroll-animations-1; type:dfn;
    text:animation-range-start
    text:animation-range-end
</pre>

<h2 id="delta">Delta specification</h2>

<p>This is a delta specification, meaning that it currently contains
only the differences from CSS Animations Level 1 [[!CSS3-ANIMATIONS]].
Once the Level 1 specification is closer to complete, it will be merged
with the additions here into a complete level 2 specification.</p>

# Animations # {#animations}

Changes to any of the animation properties defined in this specification
cause the corresponding {{CSSAnimation}} object and its associated objects
to be updated according to the correspondence between these properties
and Web Animations concepts defined in [[#keyframes]].

However, if the author modifies the animation
using the Web Animations programming interface,
the changes from the programming interface take precedence as follows:

*   After a successful call to {{KeyframeEffect/setKeyframes()}}
    on the {{KeyframeEffect}} associated with a {{CSSAnimation}},
    any subsequent change to matching ''@keyframes'' rules or the resolved value
    of the 'animation-timing-function' property for the target element
    will not be reflected in that animation.

    However, if the last matching ''@keyframes'' rule is removed
    the animation must still be canceled.

*   After a successful call to {{AnimationEffect/updateTiming()}}
    on the {{KeyframeEffect}} associated with a {{CSSAnimation}},
    for each property included in the
    {{AnimationEffect/updateTiming(timing)/timing}} parameter,
    any subsequent change to a corresponding animation property
    will not be reflected in that animation.

    For example, calling
    <code>cssAnimation.effect.updateTiming({ duration: 1000 })</code>
    would cause subsequent changes to 'animation-duration' to be ignored
    whilst changes to 'animation-delay' would still be reflected
    in the {{KeyframeEffect}}'s timing.

*   After a successful call to {{Animation/play()}} or {{Animation/pause()}}
    on a {{CSSAnimation}},
    any subsequent change to the 'animation-play-state' will no longer
    cause the {{CSSAnimation}} to be played or paused
    as defined in [[#animation-play-state]].

*   After a successful call to {{Animation/reverse()}} on a {{CSSAnimation}}
    or after successfully setting the {{Animation/startTime}}
    on a {{CSSAnimation}},
    if, as a result of that call the [=play state=] of the
    {{CSSAnimation}} changes to or from the [=play state/paused=] play state,
    any subsequent change to the 'animation-play-state' will no longer
    cause the {{CSSAnimation}} to be played or paused
    as defined in [[#animation-play-state]].

    The requirement for a change to or from the [=play state/paused=] state
    ensures that even after calling
    {{Animation/reverse()}} or setting the {{Animation/startTime}}
    on a running animation,
    the animation continues to observe changes in 'animation-play-state'.

*   After successfully setting the {{Animation/effect}} of a {{CSSAnimation}}
    to <code>null</code>
    or some {{AnimationEffect}} other than the original {{KeyframeEffect}},
    all subsequent changes to animation properties other than
    'animation-name', 'animation-play-state', or 'animation-timeline'
    will not be reflected in that animation.
    Similarly, any change to matching ''@keyframes'' rules will not be reflected
    in that animation.
    However, if the last matching ''@keyframes'' rule is removed
    the animation must still be canceled.

Note, the reference to a successful call in the above rules
is necessary to ensure that
when an exception is thrown by any of these methods,
the override behavior is <em>not</em> applied.

## Owning element ## {#owning-element-section}

The <dfn>owning element</dfn> of an animation refers to the element or
pseudo-element to which the 'animation-name' property was applied that generated
the animation.

If the 'display' property of an element is set to ''display/none''
and its 'display' value would compute to ''display/none'' when ignoring the Transitions and Animations [=cascade origins=],
then terminate running animations with this <a>owning element</a>.
If an element has a 'display' of ''display/none'' and
its 'display' value had computed to ''display/none'' when ignoring the Transitions and Animations [=cascade origins=],
updating 'display' to a value other than ''display/none''
will start all animations applied to the element by the 'animation-name' property.

Note: In practice, this means that an animation to a 'display' value of ''display/none'' will not terminate running animations
unless the style also computes to ''display/none'' without the effect of the animations.

If an animation generated using the markup defined in this specification is
later disassociated from that markup by an update to the computed value of the
'animation-name' property on the <a>owning element</a>, the animation is
disassociated from its <a>owning element</a> (that is, it has no <a>owning
element</a> from that point forwards).

<div class="note">

In the example below, <code>animation</code>'s initial <a>owning element</a>
is <code>elem</code>. <code>animation</code> is disassociated from
<code>element</code> through an update to the computed value of
<code>elem</code>'s 'animation-name' property.

<pre class="example lang-javascript">
elem.style.animation = 'spin 1s';
let animation = elem.getAnimations()[0]; // animation's owning element is elem
elem.style.animation = ""; // animation no longer has an owning element
</pre>

Note that although the <a>owning element</a> is often equal to the
[=target element=] of an animation's [=associated effect=],
this is not always the case.
The following example demonstrates some of the situations where these two
elements may differ.

<pre class="example lang-javascript">
elem.style.animation = 'move 1s';
let animation = elem.getAnimations()[0];
// animation.effect.target == elem == animation's owning element

animation.effect.target = elem2;
// animation.effect.target == elem2 != animation's owning element

animation.effect = null;
// animation.effect?.target is undefined != animation's owning element
</pre>

</div>

## Animation composite order ## {#animation-composite-order}

[=Animations=] generated from the markup defined in
this specification have an <a>animation class</a> of &lsquo;CSS
Animation&rsquo;.

CSS Animations <em>with</em> an <a>owning element</a> have a <em>later</em>
composite order than CSS Transitions but an <em>earlier</em> composite order
than animations without a specific <a>animation class</a>.

Within the set of CSS Animations <em>with</em> an <a>owning element</a>, two
animations <var>A</var> and <var>B</var> are sorted in composite order (first to
last) as follows:

1.  If the <a>owning element</a> of <var>A</var> and <var>B</var>
    differs, sort <var>A</var> and <var>B</var> by <a>tree order</a>
    of their corresponding <a>owning elements</a>.
    With regard to pseudo-elements, the sort order is as follows:

    *   element
    *   ::marker
    *   ::before
    *   any other pseudo-elements not mentioned specifically in this list,
        sorted in ascending order by the Unicode codepoints that make up each selector
    *   ::after
    *   element children

1.  Otherwise, sort <var>A</var> and <var>B</var> based on their position in the
    computed value of the 'animation-name' property of the (common) <a>owning
    element</a>.

When determining the composite order in order
to sort [[#events|animation events]]
where either or both of the events is an {{animationcancel}} event,
treat the CSS Animation(s) for which the {{animationcancel}} event was generated
as having an [=owning element=] corresponding to
the owning element in use at the moment when the CSS Animation was cancelled.
Furthermore,
use the position of the animation in the 'animation-name' property
in effect at the time when the CSS Animation was cancelled
sorting such that positions of cancelled animations sort
before positions of animations that have not been cancelled.

The composite order of CSS Animations <em>without</em> an <a>owning element</a>
is based on their position in the <a>global animation list</a>.

Issue: This differs from the behavior defined for transitions. We should
probably sort transitions first, then animation, then use the global animation
list. The reason being that when developer tools etc. hang on to orphaned
animations and transitions in order to replay them, they should maintain
roughly the same composite order.

CSS Animations generated using the markup defined in this specification are
<em>not</em> added to the <a>global animation list</a> when they are created.
Instead, these animations are appended to the <a>global animation list</a> at
the first moment when they transition out of the [=play state/idle=] play state
after being disassociated from their <a>owning element</a>.
CSS Animations that have been disassociated from their <a>owning element</a>
but are still [=play state/idle=] do not have a defined composite order.

Note, this behavior relies on the fact that disassociating an animation
from its <a>owning element</a> always causes it to enter (or remain) in the
[=play state/idle=] play state.

<h2 id="keyframes">
Assembling Keyframes</h2>

<h3 id="keyframe-rules">
Declaring Keyframes: the ''@keyframes'' rule</h3>

See [[css-animations-1#keyframes]].

<h3 id="keyframe-processing">
Processing Keyframes</h3>

For each animation effect defined by the <var ignore=''>N</var>th item
in the [=coordinated value list=] of the 'animation-*' properties
on target (pseudo-)element |element|,
its associated [=keyframes=] are generated as follows:

1.  <strong>Set Defaults:</strong>

    *   Let |default timing function| be the corresponding [=computed value=]
        of 'animation-timing-function' on |element|.

    *   Let |default composite| be the corresponding [=computed value=]
        of 'animation-composition' on |element|.

    *   Let |keyframes| be an empty sequence of [=keyframe=] objects,
        each possessing a
        |keyframe offset|,
        |keyframe timing function|,
        |keyframe composite|,
        and |keyframe values|.

    *   Let |animated properties| be an empty set of CSS [=property names=].

1.  <strong>Collect Declared Keyframes:</strong>
    1.  Find the last ''@keyframes'' at-rule in document order
        with <<keyframes-name>> matching
        the corresponding 'animation-name' value |name|.

        If there is no ''@keyframes'' at-rule
        with <<keyframes-name>> matching |name|
        (or if |name| is ''animation-name/none''),
        abort this procedure.
        In this case no animation is generated,
        and any existing animation matching |name| is canceled.

    1.  Group together all <<keyframe-block>> declarations
        that share the same [=specified value|specified=] <<keyframe-selector>>
        (treating ''@keyframe/from'' as ''0%'' and ''@keyframe/to'' as ''100%''),
        last declared 'animation-timing-function' [=computed value=]
        (defaulting to |default timing function| if there is no such declaration),
        and last declared 'animation-composition' [=computed value=]
        (defaulting to |default composite| if there is no such declaration).

    1.  For each such group of matching <<keyframe-block>> declarations,
        ordered by their earliest <<keyframe-block>> in the sorted order:

            1.  [=Cascade=] together all of its [=declaration blocks=]
                such that for each CSS property
                (except those that are “not animatable”, which must be ignored)
                the last declaration among all its <<keyframe-block>> declarations
                takes precedence.
                [[CSS-CASCADE-4]]

                Note: The [=cascade=] will
                expand [=shorthand properties=] into their [=sub-properties=]
                and map together corresponding property pairs in each [=logical property group=]
                according to the |element|’s [=computed value|computed=] [=writing mode=].

            1.  Append to |keyframes| a new empty [=keyframe=]
                with the group’s |keyframe offset|,
                |keyframe timing function|,
                and |keyframe composite|.
                Give its |keyframe values|
                the set of [=declared values=] resulting from this cascade.

            1.  Add each [=property name=] that was added to its {{CSSKeyframesRule/cssRules}}
                to |animated properties|.

1.  <strong>Generate Initial and Final Frames:</strong>

    1.  Find or create the |initial keyframe|,
        a [=keyframe=] with a |keyframe offset| of ''0%'',
        |default timing function| as its |keyframe timing function|,
        and |default composite| as its |keyframe composite|.

    1.  For any property in |animated properties|
        that is not otherwise present in a keyframe with an offset of ''0%''
        or one that would be positioned earlier in the [=used keyframe order=],
        add the [=computed value=] of that property on |element|
        to |initial keyframe|’s |keyframe values|.

    1.  If |initial keyframe|’s |keyframe values| is not empty,
        prepend |initial keyframe| to |keyframes|.

    1.  Repeat for |final keyframe|,
        using an offset of ''100%'',
        considering keyframes positioned <em>later</em> in the [=used keyframe order=],
        and <em>appending</em> to |keyframes|.

1.  <strong>Sort Frames:</strong>

    *   The <dfn lt="specified keyframe order">specified order</dfn> of |keyframes|
        is the order resulting from the steps above,
        i.e. document order with duplicate keyframes collapsed
        to the earliest position.

    *   The <dfn lt="computed keyframe order">computed order</dfn> of |keyframes|--
        which is the order returned by {{KeyframeEffect/getKeyframes()}}--
        is found by shifting any keyframes whose offset was specified as
        a <<percentage>>, ''@keyframes/from'' keyword, or ''@keyframes/to'' keyword
        to the front of the list (after the generated |initial keyframe|, if any),
        and performing a stable sort on these keyframes
        by their |keyframe offset|s.

    *   The <dfn lt="used keyframe order">used order</dfn> of |keyframes|--
        which is the order used to interpolate and compute the actual animation frames--
        is found by attaching the |keyframes|
        onto the animation effect’s timeline
        assuming an [=iteration count=] of 1
        and ordering them from earliest to latest,
        breaking ties by using the [=computed keyframe order=].

    Issue: Any specific requirements on sorting computed keyframes introduced by
    this spec should be integrated into
    [[web-animations-1#calculating-computed-keyframes]].
    Any specific requirements on used keyframes introduced by this spec
    should be integrated into
    [[web-animations-1#the-effect-value-of-a-keyframe-animation-effect]].
    The above description of the distinction between these sets of keyframes
    should be moved to an informative note.

    Note: Although the [=computed keyframe order=]
    sorts keyframes with <<percentage>> offsets,
    it maintains keyframes specified with a <<timeline-range-name>>
    in their [=specified keyframe order=]--
    after any <<percentage>> keyframes
    (other than a generated |final keyframe|),
    even if these come later in the [=used keyframe order=].

<h2 id="animation-definition">
Declaring Animations</h2>

    CSS Animations are defined by binding keyframes to an element
    using the 'animation-*' properties.
    These list-valued properties,
    which are all [=longhands=] of the 'animation' [=shorthand=],
    form a [=coordinating list property group=]
    with 'animation-name' as the [=coordinating list base property=]
    and each item in the [=coordinated value list=]
    defining the properties of a single animation effect.

    See [[css-values-4#linked-properties]]
    for how the individual 'animation-*' property values coordinate.

## The 'animation-duration' property ## {#animation-duration}

  <pre class='propdef'>
  Name: animation-duration
  Value: [ auto | <<time [0s,∞]>> ]#
  Initial: auto
  Applies to: all elements
  Inherited: no
  Percentages: N/A
  Computed value: list, each item either a time or the keyword ''animation-duration/auto''
  Animation type: not animatable
  Canonical order: per grammar
  </pre>

  The 'animation-duration' property specifies the [=iteration duration=]
  of the animation's associated [=animation effect=].

  <dl dfn-for=animation-duration dfn-type=value>
    <dt><dfn>auto</dfn>
    <dd>
      For time-driven animations,
      equivalent to ''0s''.

      For [=scroll-driven animations=],
      equivalent to the duration necessary to fill the timeline
      in consideration of 'animation-range', 'animation-delay', and 'animation-iteration-count'.
      See [[scroll-animations-1#finite-attachment]].

    <dt><dfn><<time [0s,∞]>></dfn>
    <dd>
      For time-driven animations,
      specifies the length of time that an animation takes to complete one cycle.
      A negative <<time>> is invalid.

      For [=scroll-driven animations=],
      treated as ''animation-duration/auto''.
  </dl>

  If the [=used value|used=] 'animation-duration' is ''0s'',
  the animation itself still occurs (instantaneously).
  The animation’s start and end events are still fired.
  If 'animation-fill-mode' is set to ''single-animation-fill-mode/backwards'' or ''single-animation-fill-mode/both'',
  the first frame of the animation
  (as defined by 'animation-direction')
  will be displayed during the 'animation-delay';
  and if 'animation-fill-mode' is set to ''single-animation-fill-mode/forwards'' or ''single-animation-fill-mode/both'',
  the last frame of the animation
  (as defined by 'animation-direction')
  will be displayed after the 'animation-delay'.
  However, if 'animation-fill-mode' is set to ''animation-fill-mode/none''
  the keyframes of the animation animation will have no noticeable effect.

  For backwards-compatibility with Level 1,
  when the [=computed value=] of 'animation-timeline' is ''animation-timeline/auto''
  (i.e. only one list value, and that value being ''animation-timeline/auto''),
  the [=resolved value=] of ''animation-duration/auto'' for 'animation-duration'
  is ''0s'' whenever its [=used value=] would also be ''0s''.

## The 'animation-timing-function' property ## {#animation-timing-function}

The 'animation-timing-function' is used to determine the [=timing function=]
applied to each [=keyframe=] as defined in [[#keyframes]].

## The 'animation-iteration-count' property ## {#animation-iteration-count}

The 'animation-iteration-count' property specifies the [=iteration count=]
of the animation's associated [=animation effect=].

## The 'animation-direction' property ## {#animation-direction}

The 'animation-direction' property specifies the [=playback direction=]
of the animation's associated [=animation effect=].

## The 'animation-play-state' property ## {#animation-play-state}

The 'animation-play-state' is used to pause or play the animation.

If at any time,
including when the animation is first generated,
the resolved value of 'animation-play-state'
corresponding to an animation is newly ''running'',
the implementation must run the procedure to [=play an animation=]
for the given animation
with the <var ignore>auto-rewind flag</var> set to false.

If at any time,
including when the animation is first generated,
the resolved value of 'animation-play-state'
corresponding to an animation is newly ''paused'',
the implementation must run the procedure to [=pause an animation=]
for the given animation.

The above requirements do not apply
if the animation's play state is being overridden by the Web Animations API
as described in [[#animations]].

## The 'animation-delay' property ## {#animation-delay}

The 'animation-delay' property specifies the [=start delay=]
of the animation's associated [=animation effect=].

## The 'animation-fill-mode' property ## {#animation-fill-mode}

The 'animation-fill-mode' property specifies the [=fill mode=]
of the animation's associated [=animation effect=].

## The 'animation-composition' property ## {#animation-composition}

The 'animation-composition' property defines the <a>composite operation</a>
used when multiple animations affect the same property simultaneously.

<pre class='propdef'>
Name: animation-composition
Value: <<single-animation-composition>>#
Initial: replace
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: list, each item a keyword as specified
Animation type: not animatable
Canonical order: per grammar
</pre>

<span class=prod><dfn>&lt;single-animation-composition></dfn> = replace | add | accumulate</span>

The values of 'animation-composition' have the meaning defined for the
corresponding values of the <a>composite operation</a> defined in Web
Animations [[!WEB-ANIMATIONS]].

When specified in a keyframe, 'animation-composition' defines the composite
operation to use for each property specified in that keyframe until the next
keyframe specifying each property.

<div class='example'>
  For example, the following stylesheet defines two different animations
  targeting the 'scale' property.

  <pre>
    @keyframes heartbeat {
      from {
        scale: 1;
        animation-timing-function: ease-out;
      }
      30% {
        scale: 1.3;
      }
    }
    .heartbeat {
      animation: heartbeat 0.3s 2s infinite;
    }

    @keyframes throb {
      50% {
        scale: 1.8;
      }
    }
    .icon:mouseover {
      animation: throb 0.4s add;
    }
  </pre>

  If these two animations are applied to the same element, normally only
  one animation would apply, but by specifying ''add'' as the
  'animation-composition' on the second animation, the result of the two
  animations will be combined.

  Since CSS Transitions [[CSS3-TRANSITIONS]] have a lower composite
  order, it is possible to use 'animation-composition' to combine CSS
  Animations with underlying transitions as in the following example.

  <pre>
    .icon {
      filter: blur(20px);
      transition: filter 0.5s;
    }
    .icon:hover {
      filter: blur(0px);
      animation: brightness-pulse 3s infinite add;
    }

    @keyframes brightness-pulse {
      0% {
        scale: 1.1;
        filter: brightness(130%);
      }
      10% {
        scale: 1;
        filter: brightness(100%);
      }
    }
  </pre>

  Issue: Create pictures of these examples and verify they make sense.
</div>


## The 'animation-timeline' property ## {#animation-timeline}

The 'animation-timeline' property defines the <a>timeline</a> used with the
animation.

Note: This specification does not introduce any syntax to specify animation
timelines but instead it is up to others specifications such as Scroll-linked
Animations [[SCROLL-ANIMATIONS]] to do so.

<pre class='propdef'>
Name: animation-timeline
Value: <<single-animation-timeline>>#
Initial: auto
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: list, each item either
    the keyword ''single-animation-timeline/none'',
    the keyword ''single-animation-timeline/auto'',
    a case-sensitive [=css identifier=],
    a computed ''scroll()'' function,
    or
    a computed ''view()'' function
Canonical order: per grammar
Animation Type: not animatable
</pre>

<pre class=prod>
<dfn>&lt;single-animation-timeline></dfn> = auto | none | <<dashed-ident>> | <<scroll()>> | <<view()>>
</pre>

The 'animation-timeline' property is similar to properties like 'animation-name'
and 'animation-duration' in that it can have one or more values, each one
imparting additional behavior to a corresponding [=animation=] on the element,
with the timelines matched up with animations as described
[[css-animations-1#animation-name|here]].

Each value has type <<single-animation-timeline>>, whose possible values have
the following effects:

<dl dfn-for="animation-timeline,<single-animation-timeline>" dfn-type=value>
:   <dfn>auto</dfn>
::  The animation's [=timeline=] is a {{DocumentTimeline}}, more specifically
    the <a>default document timeline</a>.

:   <dfn>none</dfn>
::  The animation is not associated with a [=timeline=].

:   <dfn><<dashed-ident>></dfn>
::  If a named [=scroll progress timeline=] or [=view progress timeline=]
    is in scope on this element,
    use the referenced timeline
    as defined in [[scroll-animations-1#timeline-scope]].

    Otherwise the animation is not associated with a [=timeline=].

:   <dfn><<scroll()>></dfn>
::  Use the [=scroll progress timeline=] indicated by the given ''scroll()'' function.
    See [[scroll-animations-1#scroll-notation]].

:   <dfn><<view()>></dfn>
::  Use the [=view progress timeline=] indicated by the given ''view()'' function.
    See [[scroll-animations-1#view-notation]].
    </dl>


Issue: Make it easier to use 'animation-name' to select the timeline when
'animation-timeline' is not specified. Allowing 'animation-name' to be used for
selecting timeline enables most common animations to have to use a single name
for both their keyframes and timeline which is simple and ergonomics. The
'animation-timeline' property gives authors additional control to independently
select keyframes and timeline if necessary.

When multiple 'animation-*' properties are set simultaneously,
'animation-timeline' is updated first,
so e.g. a change to 'animation-play-state' applies
to the simultaneously-applied timeline specified in 'animation-timeline'.


<h3 id="animation-trigger-prop">
The 'animation-trigger' property</h3>

<pre class=propdef>
Name: animation-trigger
Value: [ none | [ <<dashed-ident>> <<animation-action>>+ ]+ ]#
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: as specified
Animation type: not animatable
Canonical order: per grammar
</pre>

The 'animation-trigger' property
specifies whether the animation is a [=triggered animation=],
and if it is,
what trigger it responds to
and what actions it takes in response.
'animation-trigger' is a [=reset-only sub-property=] of the 'animation' shorthand.
Its values are:

<dl dfn-type=value dfn-for=animation-trigger>
    : <dfn>none</dfn>
    ::
        The corresponding animation is not a [=triggered animation=].

    : <dfn>[ <<dashed-ident>> <<animation-action>>+ ]+</dfn>
    ::
        The corresponding animation is a [=triggered animation=],
        responding to the triggers named by each <<dashed-ident>>,
        and responding by taking the action named by the corresponding <<animation-action>>.
        (See [[#trigger-scope]] for how <<dashed-ident>>s are resolved to [=triggers=].)

        How many <<animation-action>>s a trigger accepts,
        and what exactly activates them,
        is determined by the type of the trigger.
        <span class=note>([=Event triggers=] take one and possibly an optional second, depending on whether they're stateless or stateful;
        [=timeline triggers=] take one and optionally a second.)</span>
        Specifying the wrong number of actions
        (too many or too few)
        is valid syntactically,
        but causes the trigger to have no effect.

        If multiple triggers occur simultaneously,
        they take effect in the order specified.

        If the same <<dashed-ident>> is specified multiple times,
        all but the last have no effect.
</dl>

The possible <dfn><<animation-action>></dfn> values,
and what effect they have in each animation state:

<table class=data dfn-type=value dfn-for="<animation-action>" link-for-hint="Animation">
    <thead>
        <tr><th>Keyword<th>Extra Effect<th>initial<th>playing<th>paused<th>finished
    </thead>
    <tr><td><dfn>none</dfn><td>—<td>—<td>—<td>—<td>—
    <tr><td><dfn>play</dfn><td>—<td>{{play()}}<td>—<td>{{play()}}<td>{{play()}}
    <tr><td><dfn>play-once</dfn><td>—<td>{{play()}}<td>—<td>{{play()}}<td>—
    <tr><td><dfn>play-forwards</dfn><td>set playback rate to positive<td>{{play()}}<td>—<td>{{play()}}<td>{{play()}}
    <tr><td><dfn>play-backwards</dfn><td>set playback rate to negative<td>{{play()}}<td>—<td>{{play()}}<td>{{play()}}
    <tr><td><dfn>pause</dfn><td>—<td>—<td>{{pause()}}<td>—<td>—
    <tr><td><dfn>reset</dfn><td>set progress to 0<td>—<td>{{pause()}}<td>{{pause()}}<td>{{pause()}}
    <tr><td><dfn>replay</dfn><td>set progress to 0<td>{{play()}}<td>—<td>{{play()}}<td>{{play()}}
    <caption>
        If there is an "effect",
        it happens regardless of the current state,
        before the state-specific action
    </caption>
</table>


## The 'animation' shorthand property ## {#animation-shorthand}

The 'animation' shorthand property syntax is as follows:

<span class=prod><dfn>&lt;single-animation></dfn> = <<'animation-duration'>> || <<easing-function>> || <<'animation-delay'>> || <<single-animation-iteration-count>> || <<single-animation-direction>> || <<single-animation-fill-mode>> || <<single-animation-play-state>> || [ none | <<keyframes-name>> ] || <<single-animation-timeline>></span>


<!-- Big Text: triggers

█████▌ ████▌  ████  ███▌   ███▌  █████▌ ████▌   ███▌
  █▌   █▌  █▌  ▐▌  █▌  █▌ █▌  █▌ █▌     █▌  █▌ █▌  █▌
  █▌   █▌  █▌  ▐▌  █▌     █▌     █▌     █▌  █▌ █▌
  █▌   ████▌   ▐▌  █▌ ██▌ █▌ ██▌ ████   ████▌   ███▌
  █▌   █▌▐█    ▐▌  █▌  █▌ █▌  █▌ █▌     █▌▐█       █▌
  █▌   █▌ ▐█   ▐▌  █▌  █▌ █▌  █▌ █▌     █▌ ▐█  █▌  █▌
  █▌   █▌  █▌ ████  ███▌   ███▌  █████▌ █▌  █▌  ███▌
-->

<h2 id="animation-triggers">
Triggers</h2>

While CSS animations are, by default,
automatically run as soon as the appropriate 'animation' values have been set on an element,
the 'animation-trigger' property allows the animation's start to be delayed
until an appropriate trigger occurs,
and even paused, restarted, or reset by triggers
(making it a <dfn export>triggered animation</dfn>).

This is a simplified and streamlined version
of what can be achieved with the Web Animations API in Javascript,
allowing simple, common interaction patterns
to be created and managed purely in CSS.

Currently, two types of <dfn export for=CSS>triggers</dfn> are defined:

* [=timeline triggers=], managed by the 'timeline-trigger' properties,
    which allow animations to be triggered by entering or leaving certain timeline ranges.
    (Usually, [=view progress timelines=],
    so an animation can be started when an element comes on-screen,
    without actually <em>driving</em> the animation with the scroll progress.)

* [=event triggers=], managed by the 'event-trigger' properties,
    which allow animations to be triggered by certain user-interaction events,
    such as clicking an element or pressing certain keys.

A [=trigger=] is <em>defined</em> on some specific triggering element.
All triggers have a name,
and the specific type of trigger dictates how and when it's activated.
A trigger can define multiple "types" of activation.
(For example, [=timeline triggers=] can do different things on entry and exit.)

A [=trigger=] is <em>used</em> on potentially any element,
creating a <dfn export for=CSS>trigger instance</dfn> on the element.
(For example, 'animation-trigger' associates a [=trigger instance=]
with a specific animation on the element.)
The trigger-using element specifies what actions to take
when the [=trigger=] activates.

Note: This design for [=triggers=] and [=trigger instances=],
and the way they're associated with [=triggered animations=] and <<animation-action>>s,
is intentionally somewhat generic,
intended to support using [=triggers=] for <em>other</em> purposes in the future.
For now, though, [=triggered animations=] are the only user of this feature.


<h3 id="trigger-scope">
Trigger Scope/Resolution</h3>

All [=triggers=] are document-global by default,
similar to <l spec="css-anchor-position-1">[=anchor names=]</l>.

If a single element attempts to define multiple [=triggers=] of different types
with the same name,
it only exposes one of them,
with [=event triggers=] winning over [=timeline triggers=].

Note: This order is completely arbitrary
(based on alphabetic order of the concept name),
as this is just an error case.

If multiple elements define [=triggers=] with the same name,
the [=trigger=] defined by the later element in [=tree order=] is used.

Note: This behavior will be improved by a <css>trigger-scope</css> property,
not yet defined,
letting you define triggers that are only visible to subtrees
and references that only search in that subtree
(just like 'anchor-scope').

<!-- Big Text: timeline

█████▌ ████ █     █ █████▌ █▌    ████ █    █▌ █████▌
  █▌    ▐▌  ██   ██ █▌     █▌     ▐▌  █▌   █▌ █▌
  █▌    ▐▌  █▌█ █▐█ █▌     █▌     ▐▌  ██▌  █▌ █▌
  █▌    ▐▌  █▌ █ ▐█ ████   █▌     ▐▌  █▌▐█ █▌ ████
  █▌    ▐▌  █▌   ▐█ █▌     █▌     ▐▌  █▌  ██▌ █▌
  █▌    ▐▌  █▌   ▐█ █▌     █▌     ▐▌  █▌   █▌ █▌
  █▌   ████ █▌   ▐█ █████▌ █████ ████ █▌   ▐▌ █████▌
-->

<h3 id="timeline-triggers">
Timeline Triggers</h3>

A <dfn export>timeline trigger</dfn> is a [=trigger=]
which is activated when some [=timeline=]
enters the trigger's <dfn export for="timeline trigger">enter range</dfn>,
or leaves the trigger's <dfn export for="timeline trigger">exit range</dfn>.
It is defined on an element with the 'timeline-trigger' shorthand property,
or its longhands.

A [=timeline trigger=] has a binary <dfn export for="timeline trigger">trigger state</dfn> associated with it;
it is initially "untriggered".
While it's "untriggered",
the associated [=timeline=] entering (or starting in) the trigger's [=enter range=]
performs an associated <dfn export for="timeline trigger">enter action</dfn>
and switches the [=timeline trigger/trigger state=] to "triggered";
while it's "triggered",
the associated timeline <em>leaving</em> the trigger's [=exit range=]
performs an associated <dfn export for="timeline trigger">exit action</dfn>
and switches the [=timeline trigger/trigger state=] to "untriggered".

Note: By default, the [=exit range=] is the same as the [=enter range=];
even when manually specified,
the [=exit range=] is always a <em>superset</em> of the [=enter range=].
The two ranges allow, for example,
an 'animation-trigger' to start an animation
when an element is scrolled close the center of the screen
(using a [=view progress timeline=] with a relatively small window as the [=enter range=]),
but not stop it until the element is fully off-screen
(using <l spec="scroll-animations-1">''animation-timeline-range/cover''</l> as the [=exit range=]).

Issue: I think it's WebAnim2 that needs to define
that exit ranges are interpreted
as the bounding range of the [=enter range=]
and what's specified for the [=exit range=].

A [=timeline trigger=] can have one or two actions associated with it
when used as a trigger on an element
(such as by 'animation-trigger').
If two are specified, the first is the trigger's [=timeline trigger/enter action=]
and the second is the trigger's [=timeline trigger/exit action=];
if only one is specified, the first is the trigger's [=timeline trigger/enter action=]
and its [=timeline trigger/exit action=] is to do nothing.

An element can define multiple [=timeline triggers=],
using the same [=timeline=] (potentially with different ranges)
or different ones.
The set of 'timeline-trigger' longhands
form a [=coordinating list property group=],
with 'timeline-trigger-name' as the [=coordinating list base property=],
and each item in the [=coordinated value list=]
defining the properties of a single [=timeline trigger=].


<h4 id="timeline-trigger-name">
Naming the Trigger: the 'timeline-trigger-name' property</h4>

<pre class=propdef>
Name: timeline-trigger-name
Value: none | <<dashed-ident>>#
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: as specified
Canonical order: per grammar
Animation type: not animatable
</pre>

If ''timeline-trigger-name/none'' is specified,
the element does not define any [=timeline triggers=].

If the same <<dashed-ident>> appears multiple times in the list,
only the last one defines a [=timeline trigger=];
the preceding ones have no effect.


<h4 id="timeline-trigger-source">
Linking a Timeline: the 'timeline-trigger-source' property</h4>

<pre class='propdef'>
Name: timeline-trigger-source
Value: <<single-animation-timeline>>#
Initial: auto
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: list, each item either
  the keyword ''single-animation-timeline/none'',
  the keyword ''single-animation-timeline/auto'',
  a case-sensitive [=css identifier=],
  a computed ''scroll()'' function,
  or
  a computed ''view()'' function
Canonical order: per grammar
Animation Type: not animatable
</pre>

The 'timeline-trigger-source' property
specifies the [=timeline trigger's=] associated [=timeline=].
Values have the same meaning as those of 'animation-timeline',
except that ''timeline-trigger-source/none''
instead causes the corresponding entry in the [=coordinated value list=]
to not define a [=timeline trigger=].

<h4 id="timeline-trigger-range-prop">
The Enter Range: the 'timeline-trigger-range' property</h4>

<pre class="propdef shorthand">
Name: timeline-trigger-range
Value: [ <<'timeline-trigger-range-start'>> <<'timeline-trigger-range-end'>>? ]#
</pre>

The 'timeline-trigger-range' property is a [=shorthand property=]
that sets 'timeline-trigger-range-start' and 'timeline-trigger-range-end'
together in a single declaration.
It has the same syntax as the 'animation-range' property.

The behavior of 'timeline-trigger-range' is defined in [[web-animations-2#trigger-ranges]].

Issue: Need to rewrite WebAnim2 to use the term "enter range".

<pre class="propdef">
Name: timeline-trigger-range-start, timeline-trigger-range-end
Value: [ normal | <<length-percentage>> | <<timeline-range-name>> <<length-percentage>>? ]#
Initial: normal
Applies to: all elements
Inherited: no
Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
Computed value: list, each item either the keyword ''animation-trigger-range-start/normal'' or a timeline range and progress percentage
Animation type: not animatable
</pre>

The 'timeline-trigger-range-start' and 'timeline-trigger-range-end' properties
specify the [=timeline trigger=]’s associated [=timeline trigger/enter range=].
Values have the same meaning as 'animation-range-start' and 'animation-range-end'.


<h4 id="timeline-trigger-exit-range-prop">
The Exit Range: the 'timeline-trigger-exit-range' property</h4>

<pre class="propdef shorthand">
Name: timeline-trigger-exit-range
Value: [ <<'timeline-trigger-exit-range-start'>> <<'timeline-trigger-exit-range-end'>>? ]#
</pre>

The 'timeline-trigger-exit-range' property is a [=shorthand property=]
that sets 'timeline-trigger-exit-range-start' and 'timeline-trigger-exit-range-end'
together in a single declaration.
It has the same syntax as the 'animation-range' property.

The behavior of 'timeline-trigger-exit-range' is defined in [[web-animations-2#trigger-ranges]].


<pre class="propdef">
Name: timeline-trigger-exit-range-start, timeline-trigger-exit-range-end
Value: [ auto | normal | <<length-percentage>> | <<timeline-range-name>> <<length-percentage>>? ]#
Initial: auto
Applies to: all elements
Inherited: no
Percentages: relative to the specified [=named timeline range=] if one was specified, else to the entire timeline
Computed value: list, each item either the keyword ''animation-trigger-range-start/normal'' or a timeline range and progress percentage
Animation type: not animatable
</pre>

The 'timeline-trigger-exit-range-start' and 'timeline-trigger-exit-range-end' properties
specify the [=timeline trigger=]’s associated [=timeline trigger/exit range=].
Values have the same meaning as 'animation-range-start' and 'animation-range-end',
with the following addition:

<dl dfn-type=value dfn-for="timeline-trigger-exit-range, timeline-trigger-exit-range-start, timeline-trigger-exit-range-end">
    : <dfn>auto</dfn>
    ::
        The start (for 'timeline-trigger-exit-range-start')
        or end (for 'timeline-trigger-exit-range-end')
        is equal to the start/end of the [=timeline trigger's=] [=enter range=].
</dl>

<h4 id="timeline-trigger-shorthand">
The 'timeline-trigger' Shorthand</h4>

<pre class="propdef shorthand">
Name: timeline-trigger
Value: none | [ <<'timeline-trigger-name'>> <<'timeline-trigger-source'>> <<'timeline-trigger-range'>> [ '/' <<'timeline-trigger-exit-range'>> ]? ]#
</pre>

The 'timeline-trigger' [=shorthand property=]
sets all of 'timeline-trigger-name',
'timeline-trigger-source',
'timeline-trigger-range',
and optionally 'timeline-trigger-exit-range'
at once.

A value of <dfn value for=timeline-trigger>none</dfn>
is equivalent to ''none none normal''.

Note: Due to significant potential ambiguities in the syntax
('timeline-trigger-name' vs [=timeline=] names in 'timeline-trigger-source';
[=enter ranges=] vs [=exit ranges=]),
this shorthand's values must be given in the specified order,
rather than being settable in any order as is more common.

<!-- Big Text: event

█████▌ █▌   █▌ █████▌ █    █▌ █████▌
█▌     █▌   █▌ █▌     █▌   █▌   █▌
█▌     █▌   █▌ █▌     ██▌  █▌   █▌
████   ▐▌   █  ████   █▌▐█ █▌   █▌
█▌      █  ▐▌  █▌     █▌  ██▌   █▌
█▌      ▐▌ █   █▌     █▌   █▌   █▌
█████▌   ▐█    █████▌ █▌   ▐▌   █▌
-->

<h3 id="event-triggers">
Event Triggers</h3>

An <dfn export>event trigger</dfn> is a [=trigger=]
which is activated when certain {{Event}}s are fired at the element.
It is defined on an element with the 'event-trigger' shorthand property,
or its longhands.

An [=event trigger=] can be defined as either stateless or stateful:

* If stateless, it has a single set of <dfn for="event trigger" lt="enter event">enter events</dfn>
    that activate it.
* If stateful, it has two sets of events, its [=enter events=]
    and another set of <dfn for="event trigger" lt="exit event">exit events</dfn>.

[=Event triggers=] are activated when one of its associated {{Event}}s are fired on the page
with the trigger-defining element as its {{Event/target}}.
If it's stateful,
it has a binary <dfn export for="event trigger">trigger state</dfn> associated with it,
initially "untriggered":
while "untriggered", it only activates when the defining element receives one of its [=enter events=],
performing an associated <dfn export for="event trigger">enter action</dfn>
and switching its [=event trigger/trigger state=] to "triggered";
while "triggered", it only activates when it receives one of its [=exit events=],
performing an associated <dfn export for="event trigger">exit action</dfn>
and switching its [=event trigger/trigger state=] back to "untriggered".

A stateless [=event trigger=] must be given exactly one action for its [=trigger instance=].
A stateful one can be given one or two:
the first is its [=event trigger/enter action=],
and the second, if provided, is its [=event trigger/exit action=];
if the second is not provided,
the [=event trigger/exit action=] is to do nothing.

Note: A stateful and stateless [=event trigger=] act differently
even if you only assign a single action;
a single-action stateful [=event trigger=] will effectively "turn off"
until it receives one of its [=exit events=],
ignoring any of the [=enter events=] after the first,
while a stateless one will repeatedly trigger for every [=enter event=].

An element can define multiple [=event triggers=],
using the same {{Event}}s or different ones.
The set of 'event-trigger' longhands
form a [=coordinating list property group=],
with 'event-trigger-name' as the [=coordinating list base property=],
and each item in the [=coordinated value list=]
defining the properties of a single [=event trigger=].

Issue: The proposal I drew this text from
specified that it only cares if the element is the *target* of the event.
We probably want to allow for bubbling and/or capturing,
possibly as an opt in/out.


<h4 id="event-trigger-name">
Naming the Trigger: the 'event-trigger-name' property</h4>

<pre class=propdef>
Name: event-trigger-name
Value: none | <<dashed-ident>>#
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: as specified
Canonical order: per grammar
Animation type: not animatable
</pre>

If ''event-trigger-name/none'' is specified,
the element does not define any [=event triggers=].

If the same <<dashed-ident>> appears multiple times in the list,
only the last one defines a [=event trigger=];
the preceding ones have no effect.

<h4 id="event-trigger-source">
Linking an Event: the 'event-trigger-source' property</h4>

<pre class=propdef>
Name: event-trigger-source
Value: [ none | <<event-trigger-event>>+ [ / <<event-trigger-event>>+ ]? ]#
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: as specified
Animation type: not animatable
</pre>

The 'event-trigger-source' property
specifies what event or events activate the [=event trigger=].
Its values are:

<dl dfn-type=value dfn-for=event-trigger-source>
    : <dfn>none</dfn>
    :: The corresponding entry in the [=coordinated value list=] does not define a trigger.

    : <dfn><<event-trigger-event>>+ [ / <<event-trigger-event>>+ ]?</dfn>
    :: Defines what event(s) the [=event trigger=] responds to.

        If a ''/'' is used in the value,
        the [=event trigger=] is stateful;
        the set of events before the ''/'' are the [=event trigger's=] [=enter events=],
        while those after the ''/'' are the [=exit events=].
        (The same events can occur in both sets.)

        Otherwise,
        the [=event trigger=] is stateless,
        and the provided events are its [=enter events=].
</dl>

<pre class=prod>
<dfn><<event-trigger-event>></dfn> = activate | click | touch | dblclick | keypress(<<string>>) | ...
</pre>

Issue: Figure out the full set of events we want to handle.


<h4 id="event-trigger-shorthand">
The 'event-trigger' Shorthand</h4>

<pre class='propdef'>
Name: event-trigger
Value: none | [ <<'event-trigger-name'>> <<'event-trigger-source'>> ]#
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Computed value: as specified
Animation type: not animatable
</pre>

The 'event-trigger' [=shorthand property=]
sets both 'event-trigger-name' and 'event-trigger-source' at once.

A value of <dfn value for="event-trigger">none</dfn>
is equivalent to ''none none''.




# Animation Events # {#events}

## Event dispatch ## {#event-dispatch}

Note, this is a more general description of event dispatch than that of CSS
Animations Level 1 [[CSS3-ANIMATIONS]] since it must account for the
possibility of animations being seeked or reversed using the Web Animations API
[[WEB-ANIMATIONS]].

The [=event target|target=] for a CSS animation event is
the animation's [=owning element=].
If there is no [=owning element=], no CSS animation events are dispatched
(although the [=animation playback events=] defined in Web Animations are still
dispatched at the corresponding {{CSSAnimation}} object).

For the purpose of determining which events to dispatch, the
[[web-animations-1#animation-effect-phases-and-states|phases]] defined in
the Web Animations model are used. These definitions apply to an <a>animation
effect</a>, however, for the purpose of dispatching events, we consider a
CSS Animation to have the same phase as its [=associated effect=].
For example, a CSS Animation is in the [=animation effect/before phase=] if its
[=associated effect=] is in the [=animation effect/before phase=].

A CSS Animation that does not have an [=associated effect=]
is considered to be in the <a>idle phase</a>
if its [=animation/current time=] is <a>unresolved</a>, in the
[=animation effect/before phase=] if its <a>current time</a> is less than zero,
and in the [=animation effect/after phase=] otherwise.

Similarly, subsequent references to the <a>start delay</a>, <a>active
duration</a>, <a>current iteration</a>, <a>iteration start</a>, and
<a>iteration duration</a> of a CSS animation should be understood to refer
to the corresponding properties of the animation's [=associated effect=].

For calculating the {{AnimationEvent/elapsedTime}} of each event, the following
definitions are used:

*   <dfn>interval start</dfn> =
    <code>max(min(-<a>start delay</a>, <a>active duration</a>), 0)</code>
*   <dfn>interval end</dfn> =
    <code>max(min([=associated effect end=] - <a>start delay</a>,
                  <a>active duration</a>), 0)</code>

Each time a new [=animation frame=] is established and the animation does
<em>not</em> have a [=pending play task=] or [=pending pause task=],
the events to dispatch are determined by
comparing the animation's phase before and after establishing the new
[=animation frame=] as follows:

<table class="event-state-transitions">
  <thead>
    <tr>
      <th>Change</th>
      <th>Events dispatched</th>
      <th><dfn>Elapsed time</dfn> (ms)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>[=animation effect/idle phase|idle=] or
          [=animation effect/before phase|before=] &rarr;
          [=animation effect/active phase|active=]</td>
      <td>{{animationstart}}</td>
      <td><a>interval start</a>
      </td>
    </tr>
    <tr>
      <td rowspan="2">
        [=animation effect/idle phase|idle=] or
        [=animation effect/before phase|before=] &rarr;
        [=animation effect/after phase|after=] <a
        href="#multiple-events-note">&#x66d;</a></td>
      <td>{{animationstart}}</td>
      <td><a>interval start</a>
      </td>
    </tr>
    <tr>
      <td>{{animationend}}</td>
      <td><a>interval end</a>
      </td>
    </tr>
    <tr>
      <td>[=animation effect/active phase|active=] &rarr;
          [=animation effect/before phase|before=]</td>
      <td>{{animationend}}</td>
      <td><a>interval start</a></td>
    </tr>
    <tr>
      <td>[=animation effect/active phase|active=] &rarr;
          [=animation effect/active phase|active=]
          <em>and</em>
          the <a>current iteration</a> of the animation's [=associated effect=]
          has changed since the previous animation frame
      </td>
      <td>{{animationiteration}}</td>
      <td>(See below)
          <a href="#animation-iteration-elapsed-time">&dagger;</a></td>
    </tr>
    <tr>
      <td>[=animation effect/active phase|active=] &rarr;
          [=animation effect/after phase|after=]</td>
      <td>{{animationend}}</td>
      <td><a>interval end</a></td>
    </tr>
    <tr>
      <td>[=animation effect/after phase|after=] &rarr;
          [=animation effect/active phase|active=]</td>
      <td>{{animationstart}}</td>
      <td><a>interval end</a></td>
    </tr>
    <tr>
      <td rowspan="2">[=animation effect/after phase|after=] &rarr;
                      [=animation effect/before phase|before=] <a
                      href="#multiple-events-note">&#x66d;</a></td>
      <td>{{animationstart}}</td>
      <td><a>interval end</a></td>
    </tr>
    <tr>
      <td>{{animationend}}</td>
      <td><a>interval start</a></td>
    </tr>
    <tr>
      <td><em>not</em> [=animation effect/idle phase|idle=] and <em>not</em>
          [=animation effect/after phase|after=] &rarr;
          [=animation effect/idle phase|idle=]</td>
      <td>{{animationcancel}}</td>
      <td>The <a>active time</a> of the animation at the moment it was cancelled
          calculated using a <a>fill mode</a> of both.</td>
    </tr>
  </tbody>
</table>

<p id="multiple-events-note">&#x66d; Where multiple events are listed for
a state change, all events are dispatched in the order listed and in immediate
succession.</p>

<p id="animation-iteration-elapsed-time">&dagger; The <a>elapsed time</a> for
an {{animationiteration}} event is defined as follows:</p>

1.  Let <var>previous current iteration</var> be the <a>current iteration</a>
    from the previous animation frame.

1.  If <var>previous current iteration</var> is greater than <a>current
    iteration</a>, let <var>iteration boundary</var> be <code><a>current
    iteration</a> + 1</code>, otherwise let it be <a>current iteration</a>.

1.  The <a>elapsed time</a> is the result of evaluating
    <code>(<var>iteration boundary</var> - <a>iteration start</a>) &times;
    <a>iteration duration</a>)</code>.

Since the <a>elapsed time</a> defined in the table and procedure above is
expressed in milliseconds, it must be divided by 1,000 to produce a value in
seconds before being assigned to the {{AnimationEvent/elapsedTime}} member of
the {{AnimationEvent}}.

# DOM Interfaces # {#interface-dom}

## The CSSAnimation interface ## {#the-CSSAnimation-interface}

<pre class="idl">
[Exposed=Window]
interface CSSAnimation : Animation {
  readonly attribute CSSOMString animationName;
};
</pre>

:   <dfn attribute for=CSSAnimation>animationName</dfn>
::  The key used to find matching keyframes rules that define the
    [=associated effect=] at the point when the animation was created.
    This is the value of the 'animation-name' property that caused this
    object to be generated.

## Requirements on pending style changes ## {#requirements-on-pending-style-changes}

Various operations may affect the <a lt="computed value">computed values</a> of
properties on elements. User agents may, as an optimization, defer recomputing
these values until it becomes necessary.
However, all operations included in programming interface defined in this
specification, as well as those operations defined in Web Animations
[[!WEB-ANIMATIONS]] that may return objects or animation state defined by this
specification, must produce a result consistent with having fully processed
any such pending changes to computed values.

<div class="note">
As an example, in the following code fragment, when the specified style of
<code>elem</code> is initially updated, a user agent may defer recalculating
the computed value of the 'animation' property.

However, the {{Animatable/getAnimations()}} method called on <code>elem</code>
is specified by Web Animations and can return {{CSSAnimation}} objects as
defined in this specification.
Hence, as result of the requirements in this section, the user agent must
calculate the updated value of <code>elem</code>'s 'animation' property and
create the requested {{CSSAnimation}} object before returning its result.

<div><pre class="example lang-javascript">
elem.style.animation = 'fadeOut 1s';
elem.getAnimations()[0].pause();
</pre></div>

Similarly, reading {{Animation/playState}} may depend on pending style
changes.

<div><pre class="example lang-javascript">
elem.style.animation = 'fadeOut 1s paused';
const anim = elem.getAnimations()[0];
elem.style.animationPlayState = 'running';
console.log(anim.playState); // Should be 'running'.
</pre></div>

</div>

<h2 id="priv">
  Privacy Considerations</h2>

  No privacy concerns have been reported on this specification.

  <h2 id="sec">
  Security Considerations</h2>

  No security concerns have been reported on this specification.

<h2 id="changes">Changes</h2>

<h3 id="changes-recent">Recent Changes</h3>

<p>Changes since the <a href="https://www.w3.org/TR/2023/WD-css-animations-2-20230302/">2 March 2023 Working Draft</a> include:

<ul>
    <li>Added ''animation-duration/auto'' as the [=initial value=] of 'animation-duration'.
      (<a href="https://github.com/w3c/csswg-drafts/issues/6530">Issue 6530</a>)
    <li>Rewrote [[#keyframe-processing]]
      to re-use the [=cascade=],
      to handle non-percentage keyframe offsets,
      to handle keyframes with offsets outside the [0,1] range,
      and to use the value of 'animation-composition' as the default composite.
    <li>Reduced the cases where ''display: none'' cancel an animation.
      (<a href="https://github.com/w3c/csswg-drafts/issues/6429">Issue 6429</a>)
    <li>Cross-linked to [[css-values-4#linked-properties]] to define how the various 'animation-*' properties interact.
    <li>Clarified that among the animation properties, 'animation-timeline' is applied first.
</ul>

<h3 id="changes-level-1">Changes since CSS Animations, Level 1</h3>

<ul>
  <li>
    The interaction between CSS Animations and Web Animations is defined,
    and the concepts of the owning element and animation composite order
    are introduced.
  </li>
  <li>
    Generation of keyframe objects is described in detail.
  </li>
  <li>
    The 'animation-composition' property is introduced,
    which defines the composite operation used
    when multiple animations affect the same property simultaneously.
  </li>
  <li>
    The 'animation-timeline' property is introduced,
    which defines the timeline used with the animation.
  </li>
  <li>
    The 'animation' shorthand property is updated
    to account for these new properties.
  </li>
  <li>
    Dispatch of animation events is described.
  </li>
  <li>
    The {{CSSAnimation}} interface is added.
  </li>
  <li>
    Requirements on pending style changes are described.
  </li>
</ul>
